#!/usr/bin/env node

/**
 * Star Resonance DPS Tracker - Build Script
 * 小红猫DPS统计 - 构建脚本 小红猫版DPS统计器
 * 
 * 功能：
 * 1. 使用 pkg 打包为独立 exe 文件
 * 2. 自动处理依赖和资源文件
 * 3. 创建安装包
 * 4. 生成发布文件
 */

const fs = require('fs');
const path = require('path');
const { execSync, execFileSync, spawn } = require('child_process');
const archiver = require('archiver');
let JimpModule = null;
let pngToIco = null;

class DPSTrackerBuilder {
    constructor() {
        this.projectDir = __dirname;
        this.distDir = path.join(this.projectDir, 'dist');
        this.tempDir = path.join(this.projectDir, 'temp_build');
        this.version = '2.3.51';
        // 是否禁用图标处理（兼容某些环境下 jimp/png-to-ico/rcedit 引发的异常）
        this.noIcon = process.env.BUILD_NO_ICON === '1';
        // 是否将图标"写入 exe 资源"；默认开启，如遇问题可设置 BUILD_EXE_ICON=0 禁用
        this.embedExeIcon = process.env.BUILD_EXE_ICON !== '0';
        // 安全模式：生成图标但不修改exe资源（避免某些机器上rcedit导致的运行问题）
        this.safeIconMode = process.env.BUILD_SAFE_ICON === '1';
        this.iconSrcJpg = path.join(this.projectDir, 'redcat.JPG');
        // 若用户已提供现成 ICO，则优先使用该文件
        this.iconIcoSrc = path.join(this.projectDir, 'redcat.ico');
        this.iconIcoPath = path.join(this.tempDir, 'icon.ico');

        this.ensureDirectories();
    }

    log(message) {
        console.log(`[BUILD] ${message}`);
    }

    ensureDirectories() {
        [this.distDir, this.tempDir].forEach(dir => {
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
            }
        });
    }

    // 清理构建目录
    clean() {
        this.log('清理构建目录...');
        try {
            if (fs.existsSync(this.distDir)) {
                fs.rmSync(this.distDir, { recursive: true, force: true });
            }
            if (fs.existsSync(this.tempDir)) {
                fs.rmSync(this.tempDir, { recursive: true, force: true });
            }
            this.ensureDirectories();
            this.log('✅ 构建目录清理完成');
        } catch (err) {
            this.log(`❌ 清理失败: ${err.message}`);
            // 容错：若 dist 被占用，改用新的输出目录继续
            try {
                const ts = new Date().toISOString().replace(/[-:.TZ]/g, '').slice(0, 14);
                const fallbackDist = path.join(this.projectDir, `dist_${ts}`);
                this.distDir = fallbackDist;
                this.log(`⚠️ 使用新的输出目录: ${this.distDir}`);
                if (!fs.existsSync(this.distDir)) fs.mkdirSync(this.distDir, { recursive: true });
                if (fs.existsSync(this.tempDir)) {
                    try { fs.rmSync(this.tempDir, { recursive: true, force: true }); } catch { }
                }
                if (!fs.existsSync(this.tempDir)) fs.mkdirSync(this.tempDir, { recursive: true });
                this.log('✅ 已切换到新的输出目录，继续构建');
            } catch (e2) {
                this.log(`❌ 备用输出目录创建失败: ${e2.message}`);
                throw err; // 回退为原始错误
            }
        }
    }

    // 安装构建依赖
    async installBuildDependencies() {
        this.log('安装构建依赖...');
        try {
            // 检查是否已安装 pkg
            try {
                execSync('pkg --version', { stdio: 'pipe' });
                this.log('✅ pkg 已安装');
            } catch {
                this.log('安装 pkg...');
                execSync('npm install -g pkg', { stdio: 'inherit' });
                this.log('✅ pkg 安装完成');
            }

            // 检查是否已安装 archiver (用于创建压缩包)
            try {
                require.resolve('archiver');
                this.log('✅ archiver 已安装');
            } catch {
                this.log('安装 archiver...');
                execSync('npm install archiver', { stdio: 'inherit' });
                this.log('✅ archiver 安装完成');
            }

            // 可选：安装图片与图标处理依赖（用于设置 exe 图标）
            if (!this.noIcon) {
                const hasIco = fs.existsSync(this.iconIcoSrc);
                if (!hasIco) {
                    // 仅当需要从 JPG 生成 ICO 时才安装 jimp/png-to-ico
                    try {
                        JimpModule = require('jimp');
                        this.log('✅ jimp 已安装');
                    } catch {
                        this.log('安装 jimp 用于图像处理...');
                        execSync('npm install jimp', { stdio: 'inherit' });
                        JimpModule = require('jimp');
                        this.log('✅ jimp 安装完成');
                    }

                    try {
                        pngToIco = require('png-to-ico');
                        this.log('✅ png-to-ico 已安装');
                    } catch {
                        this.log('安装 png-to-ico 用于生成 ICO 图标...');
                        execSync('npm install png-to-ico', { stdio: 'inherit' });
                        pngToIco = require('png-to-ico');
                        this.log('✅ png-to-ico 安装完成');
                    }
                } else {
                    this.log('已检测到 redcat.ico，跳过 jimp/png-to-ico 安装');
                }

                // 检查 rcedit 是否可用
                try {
                    const rceditPath = path.join(this.projectDir, 'node_modules', 'rcedit', 'bin', 'rcedit.exe');
                    if (fs.existsSync(rceditPath)) {
                        this.log('✅ rcedit 已安装');
                    } else {
                        this.log('安装 rcedit 用于给 exe 设置图标...');
                        execSync('npm install rcedit', { stdio: 'inherit' });
                        this.log('✅ rcedit 安装完成');
                    }
                } catch (err) {
                    this.log(`⚠️ rcedit 安装失败: ${err.message}`);
                }
            } else {
                this.log('⏭️ 跳过图标相关依赖安装 (--no-icon)');
            }

        } catch (err) {
            this.log(`❌ 构建依赖安装失败: ${err.message}`);
            throw err;
        }
    }

    // 准备构建文件
    prepareBuildFiles() {
        this.log('准备构建文件...');

        // 创建临时的 package.json 用于 pkg
        const pkgConfig = {
            name: 'star-resonance-dps-tracker',
            version: this.version,
            main: 'app.js',
            bin: 'app.js',
            pkg: {
                targets: ['node18-win-x64'],
                outputPath: this.distDir,
                assets: [
                    'public/**/*',
                    'floating_overlay/**/*',
                    'algo/**/*',
                    'skill_names*.json',
                    'nicknames.json',
                    'skill_names.json',
                    'package.json',
                    'install.py',
                    'README.md',
                    'LICENSE',
                    // 确保以下脚本可被从快照中以 fs 方式读取并释放
                    'server.js',
                    'server_wrapper.js',
                    'create_config.js',
                    'analyze_output.js'
                ],
                scripts: [
                    'server.js',
                    'server_wrapper.js',
                    'create_config.js',
                    'analyze_output.js'
                ]
            }
        };

        fs.writeFileSync(
            path.join(this.tempDir, 'package.json'),
            JSON.stringify(pkgConfig, null, 2)
        );

        // 复制必要文件到临时目录
        const filesToCopy = [
            'app.js',
            'server.js',
            'server_wrapper.js',
            'create_config.js',
            'analyze_output.js',
            'install.py',
            'README.md',
            'LICENSE',
            'nicknames.json',
            'skill_names.json',
            'package.json'
        ];

        filesToCopy.forEach(file => {
            if (fs.existsSync(path.join(this.projectDir, file))) {
                fs.copyFileSync(
                    path.join(this.projectDir, file),
                    path.join(this.tempDir, file)
                );
            }
        });

        // 复制目录
        const dirseToCopy = ['public', 'floating_overlay', 'algo'];
        dirseToCopy.forEach(dir => {
            const srcDir = path.join(this.projectDir, dir);
            const destDir = path.join(this.tempDir, dir);
            if (fs.existsSync(srcDir)) {
                this.copyDirectory(srcDir, destDir);
            }
        });

        // 复制配置文件
        const configFiles = fs.readdirSync(this.projectDir)
            .filter(file => file.startsWith('skill_names') && file.endsWith('.json'));

        configFiles.forEach(file => {
            fs.copyFileSync(
                path.join(this.projectDir, file),
                path.join(this.tempDir, file)
            );
        });

        this.log('✅ 构建文件准备完成');
    }

    /**
     * 获取 Jimp 类，兼容不同导出形态
     */
    getJimpClass() {
        // 兼容 require('jimp') 返回 { Jimp } / default / 直接类
        return (JimpModule && (JimpModule.Jimp || JimpModule.default || JimpModule)) || null;
    }

    /**
     * 生成 ICO 图标（从 redcat.JPG 转换），仅在源图存在时执行
     */
    async generateIconIfPossible() {
        if (this.noIcon) {
            this.log('⏭️ 跳过图标生成 (--no-icon)');
            return null;
        }
        try {
            // 1) 优先使用项目根目录现成的 redcat.ico
            if (fs.existsSync(this.iconIcoSrc)) {
                this.log(`检测到现成 ICO: ${this.iconIcoSrc}`);
                return this.iconIcoSrc;
            }

            // 2) 若无 ICO，尝试从 redcat.JPG 生成 ICO
            if (!fs.existsSync(this.iconSrcJpg)) {
                this.log('未检测到 redcat.JPG，跳过图标生成');
                return null;
            }
            const JimpClass = this.getJimpClass();
            if (!JimpClass || typeof JimpClass.read !== 'function') {
                throw new Error('Jimp.read 不可用');
            }
            // 确保临时目录存在
            if (!fs.existsSync(this.tempDir)) {
                fs.mkdirSync(this.tempDir, { recursive: true });
            }

            // 读取一次，按不同尺寸生成 PNG buffer
            const base = await JimpClass.read(this.iconSrcJpg);
            const sizes = [16, 24, 32, 48, 64, 128, 256];
            const pngBuffers = [];
            for (const size of sizes) {
                const clone = base.clone();
                clone.resize(size, size);
                const buf = await clone.getBufferAsync('image/png');
                pngBuffers.push(buf);
            }
            const icoBuffer = await pngToIco(pngBuffers);
            fs.writeFileSync(this.iconIcoPath, icoBuffer);
            this.log(`✅ 已生成图标: ${this.iconIcoPath}`);
            return this.iconIcoPath;
        } catch (err) {
            this.log(`⚠️ 图标生成失败（将继续无图标构建）: ${err.message}`);
            return null;
        }
    }

    copyDirectory(src, dest) {
        if (!fs.existsSync(dest)) {
            fs.mkdirSync(dest, { recursive: true });
        }

        const entries = fs.readdirSync(src, { withFileTypes: true });

        for (const entry of entries) {
            const srcPath = path.join(src, entry.name);
            const destPath = path.join(dest, entry.name);

            if (entry.isDirectory()) {
                this.copyDirectory(srcPath, destPath);
            } else {
                fs.copyFileSync(srcPath, destPath);
            }
        }
    }

    // 使用 pkg 打包
    async buildExecutable() {
        this.log('开始打包可执行文件...');
        try {
            const exeName = `小红猫DPS-v${this.version}.exe`;
            const outputPath = path.join(this.distDir, exeName);
            const entryPath = path.join(this.tempDir, 'app.js');

            // 可选：预生成 ICO 图标
            const icoPath = await this.generateIconIfPossible();

            // 使用 pkg 打包，显式传入 --assets（使用双引号/或不加引号，避免 Windows 单引号失效）
            const assetPatterns = [
                'public/**/*',
                'floating_overlay/**/*',
                'algo/**/*',
                'skill_names*.json',
                'nicknames.json',
                'skill_names.json',
                'package.json',
                'package-lock.json',
                'server.js',
                'server_wrapper.js',
                'create_config.js',
                'analyze_output.js'
            ];

            const assetsFlags = assetPatterns.map(p => `--assets ${p}`).join(' ');

            let pkgCommand = [
                'pkg',
                entryPath,
                '--target', 'node18-win-x64',
                '--output', outputPath,
                assetsFlags,
                // 若强制写入 exe 图标，禁用压缩可规避极少数机器资源写入后的异常
                this.embedExeIcon ? '' : '--compress GZip'
            ].join(' ');
            try {
                execSync('npx --yes pkg --version', { stdio: 'ignore' });
                pkgCommand = [
                    'npx --yes pkg',
                    entryPath,
                    '--target', 'node18-win-x64',
                    '--output', outputPath,
                    assetsFlags,
                    (this.embedExeIcon ? '' : '--compress GZip')
                ].join(' ');
            } catch (e) { }

            this.log(`执行打包命令: ${pkgCommand}`);
            execSync(pkgCommand, {
                cwd: this.tempDir,
                stdio: 'inherit',
                maxBuffer: 1024 * 1024 * 10 // 10MB buffer
            });

            if (fs.existsSync(outputPath)) {
                const stats = fs.statSync(outputPath);
                const fileSizeMB = (stats.size / 1024 / 1024).toFixed(2);
                this.log(`✅ 打包成功: ${exeName} (${fileSizeMB} MB)`);

                // 设置 exe 图标（Windows）
                if (this.embedExeIcon && !this.noIcon && !this.safeIconMode && icoPath && process.platform === 'win32') {
                    let iconSetSuccess = false;
                    let originalExePath = outputPath;
                    let backupPath = outputPath + '.backup';

                    try {
                        this.log('开始为 exe 设置图标...');

                        // 创建exe备份
                        fs.copyFileSync(outputPath, backupPath);
                        this.log('已创建exe备份文件');

                        // 等待一下确保文件完全写入
                        await new Promise(resolve => setTimeout(resolve, 1000));

                        // 尝试多种图标设置方法
                        const methods = [
                            {
                                name: '本地rcedit.exe',
                                action: async () => {
                                    const localRcedit = path.join(this.projectDir, 'node_modules', 'rcedit', 'bin', 'rcedit.exe');
                                    if (fs.existsSync(localRcedit)) {
                                        execSync(`"${localRcedit}" "${outputPath}" --set-icon "${icoPath}"`, {
                                            stdio: 'inherit',
                                            timeout: 30000
                                        });
                                        return;
                                    }
                                    throw new Error('本地rcedit.exe不存在');
                                }
                            },
                            {
                                name: 'npx rcedit',
                                action: async () => {
                                    execSync(`npx rcedit "${outputPath}" --set-icon "${icoPath}"`, {
                                        stdio: 'inherit',
                                        timeout: 30000
                                    });
                                }
                            },
                            {
                                name: '全局rcedit',
                                action: async () => {
                                    execSync(`rcedit "${outputPath}" --set-icon "${icoPath}"`, {
                                        stdio: 'inherit',
                                        timeout: 30000
                                    });
                                }
                            }
                        ];

                        // 依次尝试每种方法
                        for (const method of methods) {
                            try {
                                this.log(`尝试使用: ${method.name}`);
                                await method.action();

                                // 验证exe是否还能正常运行
                                try {
                                    execSync(`"${outputPath}" --version`, { timeout: 5000, stdio: 'pipe' });
                                    iconSetSuccess = true;
                                    this.log(`✅ 图标设置成功 (${method.name})`);
                                    break;
                                } catch (testErr) {
                                    this.log(`⚠️ ${method.name} 设置图标后exe验证失败，恢复备份`);
                                    fs.copyFileSync(backupPath, outputPath);
                                    throw new Error('exe验证失败');
                                }
                            } catch (err) {
                                this.log(`⚠️ ${method.name} 失败: ${err.message}`);
                                // 如果exe被损坏，恢复备份
                                if (fs.existsSync(backupPath)) {
                                    fs.copyFileSync(backupPath, outputPath);
                                }
                                continue; // 尝试下一个方法
                            }
                        }

                        if (!iconSetSuccess) {
                            this.log('⚠️ 所有图标设置方法都失败');
                            this.log('💡 exe文件功能正常，仅图标显示可能受影响');
                        }

                    } catch (err) {
                        this.log(`❌ 图标设置过程出错: ${err.message}`);
                        // 确保恢复到可用状态
                        if (fs.existsSync(backupPath)) {
                            fs.copyFileSync(backupPath, outputPath);
                            this.log('已恢复到无图标版本，确保exe可正常运行');
                        }
                    } finally {
                        // 清理备份文件
                        if (fs.existsSync(backupPath)) {
                            try {
                                fs.unlinkSync(backupPath);
                                this.log('✅ 备份文件已清理');
                            } catch (cleanupErr) {
                                this.log(`⚠️ 备份文件清理失败: ${cleanupErr.message}`);
                            }
                        }
                    }



                } else {
                    if (icoPath && !this.noIcon) {
                        this.log('ℹ️ 图标设置已禁用。如需启用，请设置环境变量 BUILD_EXE_ICON=1');
                    } else {
                        this.log('ℹ️ 未生成图标（--no-icon 或缺少图标文件）。');
                    }
                }
                return outputPath;
            } else {
                throw new Error('打包文件未生成');
            }

        } catch (err) {
            this.log(`❌ 打包失败: ${err.message}`);
            throw err;
        }
    }

    // 在 dist 创建与 exe 同级的 runtime 目录，放置外部运行所需资源
    createSidecarRuntime() {
        this.log('准备 sidecar runtime 目录...');
        const runtimeDist = path.join(this.distDir, 'runtime');
        if (fs.existsSync(runtimeDist)) {
            try { fs.rmSync(runtimeDist, { recursive: true, force: true }); } catch { }
        }
        fs.mkdirSync(runtimeDist, { recursive: true });

        const filesToCopy = [
            'server.js',
            'server_wrapper.js',
            'create_config.js',
            'analyze_output.js',
            'package.json',
            'package-lock.json',
            'nicknames.json',
            'skill_names.json'
        ];
        for (const f of filesToCopy) {
            const src = path.join(this.projectDir, f);
            if (fs.existsSync(src)) {
                fs.copyFileSync(src, path.join(runtimeDist, f));
            }
        }

        const dirsToCopy = ['public', 'algo', 'floating_overlay'];
        for (const d of dirsToCopy) {
            const srcDir = path.join(this.projectDir, d);
            const destDir = path.join(runtimeDist, d);
            if (fs.existsSync(srcDir)) {
                this.copyDirectory(srcDir, destDir);
            }
        }

        // 复制 skill_names*.json 动态配置
        const extraConfigs = fs.readdirSync(this.projectDir).filter(n => n.startsWith('skill_names') && n.endsWith('.json'));
        for (const name of extraConfigs) {
            fs.copyFileSync(path.join(this.projectDir, name), path.join(runtimeDist, name));
        }

        this.log('✅ sidecar runtime 准备完成');
        return runtimeDist;
    }

    // 创建完整版压缩包
    async createPortablePackage(exePath, runtimeDist) {
        this.log('创建完整版压缩包...');

        const zipName = `小红猫DPS统计-v${this.version}-完整版.zip`;
        const zipPath = path.join(this.distDir, zipName);

        // 方案A：优先使用 archiver
        try {
            await new Promise((resolve, reject) => {
                const output = fs.createWriteStream(zipPath);
                const archive = archiver('zip', { zlib: { level: 9 } });

                output.on('close', () => {
                    const fileSizeMB = (archive.pointer() / 1024 / 1024).toFixed(2);
                    this.log(`✅ 完整版创建成功: ${zipName} (${fileSizeMB} MB)`);
                    resolve();
                });
                output.on('error', (e) => reject(e));

                archive.on('error', (err) => reject(err));
                archive.pipe(output);

                // 添加主程序
                archive.file(exePath, { name: path.basename(exePath) });

                // 若项目根目录存在 redcat.ico，则一并放入压缩包（方便分发说明/替换）
                const icoInProject = path.join(this.projectDir, 'redcat.ico');
                const tempIcoPath = path.join(this.tempDir, 'icon.ico');
                if (fs.existsSync(icoInProject)) {
                    archive.file(icoInProject, { name: 'redcat.ico' });
                } else if (fs.existsSync(tempIcoPath)) {
                    // 如果是从JPG生成的ICO，也加入压缩包
                    archive.file(tempIcoPath, { name: 'redcat.ico' });
                }



                // 添加说明文件
                const readmeContent = this.generateReadme();
                archive.append(readmeContent, { name: '使用说明.txt' });

                // 添加版本信息
                const versionInfo = this.generateVersionInfo();
                archive.append(versionInfo, { name: '版本信息.txt' });

                // 打包 runtime 目录
                if (runtimeDist && fs.existsSync(runtimeDist)) {
                    archive.directory(runtimeDist, 'runtime');
                }

                archive.finalize();
            });
            return zipPath;
        } catch (err) {
            this.log(`⚠️ 完整版创建失败(archiver): ${err.message}`);
            // 方案B：回退到 PowerShell Compress-Archive（在 dist 目录相对打包）
            try {
                const exeBase = path.basename(exePath);
                const ps = process.platform === 'win32' ? 'powershell' : null;
                if (!ps) throw new Error('非 Windows 平台无法回退 Compress-Archive');
                const cmd = `${ps} -NoProfile -ExecutionPolicy Bypass -Command "Compress-Archive -Path '${exeBase}','runtime/*' -DestinationPath '${zipName}' -Force"`;
                this.log('使用 Compress-Archive 回退打包...');
                execSync(cmd, { cwd: this.distDir, stdio: 'inherit' });
                this.log(`✅ 完整版创建成功(回退): ${zipName}`);
                return zipPath;
            } catch (e2) {
                this.log(`❌ 完整版创建失败(回退): ${e2.message}`);
                // 不再抛出，避免中断整体构建
                return null;
            }
        }
    }

    generateReadme() {
        return `小红猫DPS统计 v${this.version} - 使用说明

=== 快速开始 ===
1. 双击"小红猫DPS统计-v${this.version}.exe"启动程序
2. 程序会自动检测环境并修复依赖问题
3. 默认仅启动桌面悬浮窗；如需网页端，请手动打开 http://localhost:8989
4. 进入游戏《星痕共鸣》开始战斗即可采集数据

=== 功能特点 ===
✅ 一键启动，无需安装依赖
✅ 自动环境检测和修复
✅ 实时DPS/HPS/承伤数据统计
✅ 桌面透明悬浮窗显示（支持置顶、穿透）
✅ 详细技能伤害分析
✅ 支持多玩家数据显示

=== 系统要求 ===
- Windows 10/11 (64位)
- 管理员权限(用于网络包捕获)
- 至少 100MB 可用磁盘空间
- 稳定的网络连接

=== 常见问题 ===
Q: 程序无法启动/秒退？
A: 右键以管理员身份运行；若仍失败，请查看 dist/launcher.log 并将日志反馈。

Q: 无法捕获游戏数据/没有DPS？
A: 以管理员运行；检查防火墙允许；首次运行等待依赖安装完成；确认游戏处于战斗场景。
A：检查自己的网络端口 修改根目录下的 launcher_config.json 里修改‘3’ 改为你的网卡数字。

Q: 端口 8989 被占用？
A: 程序会尝试释放端口；若失败，结束占用进程或重启系统后再试。

Q: 悬浮窗不显示/黑屏？
A: 等待 Electron 依赖自动安装；若失败，进入 runtime\\floating_overlay 目录执行 npm install；或使用系统浏览器访问 http://127.0.0.1:8989。

Q: 解析数据异常（无承伤/治疗）？
A: 请确保包内 runtime\\algo 下存在 packet.js、pb.js、blueprotobuf.js 三个文件；若缺失请重新解压或重新下载最新版。

=== 技术支持 ===
源码作者: Dimole <dmlgzs@qq.com>
作者: RdILy <1470950477@qq.com>
作者: the_wym <953759174@qq.com>


=== 版本历史 ===
v2.1.0 - 统一桌面版本
- 集成所有功能到单个exe文件
- 自动环境检测和依赖修复
- 优化启动流程和用户体验
- 增强错误处理和诊断功能
小红猫v2.1.4
- 优化样式 优化锁定解锁bug


祝您游戏愉快！
`;
    }

    generateVersionInfo() {
        return `小红猫v2.1.4 版本信息

版本号: ${this.version}
构建时间: ${new Date().toLocaleString('zh-CN')}
构建平台: ${process.platform} ${process.arch}
Node.js版本: ${process.version}

组件信息:
- 主服务器: Express + Socket.IO
- 网络捕获: libpcap (cap)
- 数据解析: protobufjs
- 桌面悬浮窗: Electron
- 打包工具: pkg

技术特性:
✅ 零安装部署
✅ 自动依赖管理
✅ 实时数据处理
✅ 跨进程通信
✅ 智能错误恢复

许可证: AGPL-3.0
作者: Dimole <dmlgzs@qq.com>
开源地址：https://github.com/dmlgzs/StarResonanceDamageCounter
作者: RdILy <1470950477@qq.com>
作者: the_wym <953759174@qq.com>
开源地址: https://gitee.com/yaojialu/desktop-dps.git`;
    }

    // 创建安装程序 (可选)
    async createInstaller() {
        this.log('创建安装程序功能暂未实现');
        this.log('当前提供懒人版，用户可直接运行exe文件');
    }

    // 清理临时文件
    cleanup() {
        this.log('清理临时文件...');
        try {
            if (fs.existsSync(this.tempDir)) {
                fs.rmSync(this.tempDir, { recursive: true, force: true });
            }
            this.log('✅ 临时文件清理完成');
        } catch (err) {
            this.log(`⚠️ 临时文件清理失败: ${err.message}`);
        }
    }

    // 显示构建结果
    showResults() {
        this.log('\n' + '='.repeat(60));
        this.log('构建完成！');
        this.log('='.repeat(60));

        const distFiles = fs.readdirSync(this.distDir);

        this.log('生成的文件:');
        distFiles.forEach(file => {
            const filePath = path.join(this.distDir, file);
            const stats = fs.statSync(filePath);
            const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
            this.log(`  📦 ${file} (${sizeMB} MB)`);
        });

        this.log('\n发布说明:');
        this.log('  1. exe文件可直接运行，无需安装');
        this.log('  2. 首次运行需要管理员权限');
        this.log('  3. 程序会自动检测和修复环境问题');
        this.log('  4. 支持离线运行（除了依赖下载）');
        this.log('\n' + '='.repeat(60));
    }

    // 主构建流程
    async build() {
        try {
            console.log(`🚀 开始构建 小红猫DPS统计 v${this.version}\n`);

            // 1. 清理
            this.clean();

            // 2. 安装构建依赖
            await this.installBuildDependencies();

            // 3. 准备文件
            this.prepareBuildFiles();

            // 4. 先准备与 exe 同目录的 runtime（最兼容：即便后续 pkg 异常退出也能保留 runtime）
            const runtimeDist = this.createSidecarRuntime();

            // 5. 打包可执行文件
            const exePath = await this.buildExecutable();

            // 6. 创建完整版
            await this.createPortablePackage(exePath, runtimeDist);
            this.log('📦 完整版打包步骤已完成，准备清理临时文件');

            // 7. 清理临时文件
            this.cleanup();
            this.log('🧹 清理步骤已完成，准备展示构建结果');

            // 8. 显示结果
            this.showResults();

        } catch (err) {
            this.log(`\n❌ 构建失败: ${err.message}`);
            this.cleanup();
            process.exit(1);
        }
    }
}

// 命令行参数处理
if (require.main === module) {
    const args = process.argv.slice(2);
    if (args.includes('--no-icon')) {
        process.env.BUILD_NO_ICON = '1';
    }
    const builder = new DPSTrackerBuilder();

    if (args.includes('--clean')) {
        builder.clean();
    } else if (args.includes('--help')) {
        console.log(`
小红猫DPS统计 构建脚本

用法:
  node build.js              构建完整版本（默认安全模式）
  node build.js --no-icon    跳过图标处理（完全无图标）
  node build.js --clean      仅清理构建目录
  node build.js --help       显示帮助信息

环境变量:
  BUILD_NO_ICON=1           跳过所有图标处理
  BUILD_EXE_ICON=0          禁用exe资源图标嵌入
  BUILD_SAFE_ICON=1         启用安全模式（生成图标但不嵌入exe）

默认行为: 自动嵌入图标到exe文件，带备份和验证机制确保exe正常运行

输出:
  dist/小红猫DPS-v2.3.0.exe        - 主程序
  dist/小红猫DPS统计-v2.3.0-完全体.zip - 完全体压缩包
`);
    } else {
        builder.build().catch(err => {
            console.error('构建失败:', err);
            process.exit(1);
        });
    }
}

module.exports = DPSTrackerBuilder;

